#include <iostream>
#include <fstream>
#include <ctime>
#include <chrono>
#include <thread>
#include <mutex>
#include <numeric>
#include <cmath>
#include <condition_variable>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/optional_debug_tools.h"
#include "tensorflow/lite/delegates/nnapi/nnapi_delegate.h"
#include "tts_lib_intf.h"
#include "tts_lib.h"
#include "tts_dict.h"
using namespace std;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   #define SWAP4(a) { \
      int t = (reinterpret_cast<char*>(&a))[0];\
              (reinterpret_cast<char*>(&a))[0]=(reinterpret_cast<char*>(&a))[3];\
              (reinterpret_cast<char*>(&a))[3]=t;\
          t = (reinterpret_cast<char*>(&a))[1];\
              (reinterpret_cast<char*>(&a))[1]=(reinterpret_cast<char*>(&a))[2];\
              (reinterpret_cast<char*>(&a))[2]=t;}
#else
   #define SWAP4(a)
#endif
#define SET_OFFSET(name) {\
        offset1 = *(reinterpret_cast<uint32_t*>(model_buff.data()+((name)-1)*sizeof(uint32_t)));\
        offset2 = *(reinterpret_cast<uint32_t*>(model_buff.data()+(name)*sizeof(uint32_t)));\
        SWAP4(offset1);\
        SWAP4(offset2);}

#define TFLITE_MINIMAL_CHECK(x)                              \
  if (!(x)) {                                                \
    fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
    exit(1);                                                 \
  }
//#define DEBUG true
#ifdef DEBUG
#define DBGpdata(name,len,dim,buf)\
{\
    std::cout<<__LINE__<<" "<<name<<" "<<len<<" "<<dim<<std::endl;\
    for (int i=0;i<len;i++){\
        for(int j=0;j<5;j++){\
            std::cout<<*(buf + i*dim+j)<<" ";\
        }\
        for(int j=dim-5;j<dim;j++){\
            std::cout<<*(buf + i*dim+j)<<" ";\
        }\
        std::cout<<std::endl;\
    }\
}
#define DBGptime()\
{\
    std::chrono::time_point<std::chrono::steady_clock> finish = std::chrono::steady_clock::now();\
    std::cout<<__LINE__<<" proctime(ms) : "<<chrono::duration_cast<chrono::milliseconds>(finish-_start).count()<<"\n";\
}
#define DBGprint(name,value)\
{\
    std::cout<<__LINE__<<" "<<name<<" "<<value<<"\n";\
}
#else
#define DBGpdata(name,len,dim,buf)
#define DBGptime()
#define DBGprint(name,value)
#endif
std::shared_ptr<TtsModelFact> g_ModelFact = nullptr;

TtsModelFact::~TtsModelFact(){
    //std::cout<<"model fact destruct\n";
}
TtsModelFact::TtsModelFact(std::string& model_path,std::string& model_fix){
    // Load model
    txtenc_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/txtenc.tflite").c_str());
    TFLITE_MINIMAL_CHECK(txtenc_model != nullptr);
    emot_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/emot.tflite").c_str());
    TFLITE_MINIMAL_CHECK(emot_model != nullptr);
    varadp_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/varadp.tflite").c_str());
    TFLITE_MINIMAL_CHECK(varadp_model != nullptr);
    duration_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/duration.tflite").c_str());
    TFLITE_MINIMAL_CHECK(duration_model != nullptr);
    LR_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/LR.tflite").c_str());
    TFLITE_MINIMAL_CHECK(LR_model != nullptr);
    dursin_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/dursin.tflite").c_str());
    TFLITE_MINIMAL_CHECK(dursin_model != nullptr);
    mem_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/mem.tflite").c_str());
    TFLITE_MINIMAL_CHECK(mem_model != nullptr);
    attenH_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/attenH.tflite").c_str());
    TFLITE_MINIMAL_CHECK(attenH_model != nullptr);
    getmask_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/getmask.tflite").c_str());
    TFLITE_MINIMAL_CHECK(getmask_model != nullptr);
    dec1_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/meldec1.tflite").c_str());
    TFLITE_MINIMAL_CHECK(dec1_model != nullptr);
    for(int layi = 0;layi<_pnca_num;layi++){
        std::string pnca_name("/dec2pnca_");
        pnca_name += (std::to_string(layi))+".tflite";
        std::shared_ptr<tflite::FlatBufferModel> pnca_model =
            tflite::FlatBufferModel::BuildFromFile((model_path+pnca_name).c_str());
        TFLITE_MINIMAL_CHECK(pnca_model != nullptr);
        dec2_pncas_model.push_back(std::move(pnca_model));
    }

    dec2_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/meldec2.tflite").c_str());
    TFLITE_MINIMAL_CHECK(dec2_model != nullptr);
    post_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/post.tflite").c_str());
    TFLITE_MINIMAL_CHECK(post_model != nullptr);
    post0_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/post0.tflite").c_str());
    TFLITE_MINIMAL_CHECK(post0_model != nullptr);
    post1_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/post1.tflite").c_str());
    TFLITE_MINIMAL_CHECK(post1_model != nullptr);
    post2_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/post2.tflite").c_str());
    TFLITE_MINIMAL_CHECK(post2_model != nullptr);
    post3_model =
        tflite::FlatBufferModel::BuildFromFile((model_path+"/post3.tflite").c_str());
    TFLITE_MINIMAL_CHECK(post3_model != nullptr);
    dnorm_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/dnorm.tflite").c_str());
    TFLITE_MINIMAL_CHECK(dnorm_model != nullptr);
    hifigan0_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan0.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan0_model != nullptr);
    hifigan1_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan1.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan1_model != nullptr);
    hifigan2_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan2.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan2_model != nullptr);
    hifigan3_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan3.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan3_model != nullptr);
    hifigan4_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan4.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan4_model != nullptr);
    hifigan5_model =
        tflite::FlatBufferModel::BuildFromFile((model_fix+"/hifigan5.tflite").c_str());
    TFLITE_MINIMAL_CHECK(hifigan5_model != nullptr);


    resolver = std::make_shared<tflite::ops::builtin::BuiltinOpResolver>();
    TFLITE_MINIMAL_CHECK(resolver != nullptr);
    //////////////////////////////////////////////////////////////////////////////
    std::string file_name(model_path+"/se.bin");
    ifstream ifs(file_name, std::ios::binary|std::ios::in);
    //TFLITE_MINIMAL_CHECK(ifs.is_open());
    if (ifs.is_open())
    {
        ifs.seekg(0,std::ios::end);
        int len = ifs.tellg();
        ifs.seekg(0,std::ios::beg);
        if (len == sizeof(float)*192){
           spk_embedding.resize(192); 
           ifs.read((char*)spk_embedding.data(), len);
           //for(auto it = spk_embedding.begin();it != spk_embedding.end();++it)
           //    std::cout<<*it<<std::endl;
        }else{
            std::cout<<"failure invalid se.bin!\n";
            exit(-1);
        }
    }else{
        std::cout<<"failure se.bin not exist!\n";
        exit(-1);
    }


    std::cout<<"init model Fact success\n";
}

TtsModel::~TtsModel(){
    //std::cout<<__LINE__<<"asrmode destruct\n";
}
TtsModel::TtsModel(std::string& model_path,std::string& model_fix)
{
    // Load model
    //if (g_ModelFact == nullptr){
        g_ModelFact.reset();
        g_ModelFact = std::make_shared<TtsModelFact>(model_path,model_fix);
    //}
    fact = g_ModelFact;
    TFLITE_MINIMAL_CHECK(fact != nullptr);
    //fact = std::make_shared<AsrModelFact>(model_path);

    //make builder
    txtenc_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->txtenc_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(txtenc_builder != nullptr);
    emot_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->emot_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(emot_builder != nullptr);
    varadp_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->varadp_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(varadp_builder != nullptr);
    duration_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->duration_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(duration_builder != nullptr);
    LR_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->LR_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(LR_builder != nullptr);
    dursin_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->dursin_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(dursin_builder != nullptr);
    mem_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->mem_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(mem_builder != nullptr);
    attenH_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->attenH_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(attenH_builder != nullptr);
    getmask_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->getmask_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(getmask_builder != nullptr);
    dec1_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->dec1_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(dec1_builder != nullptr);

    for(int layi = 0;layi<fact->_pnca_num;layi++){
        std::shared_ptr<tflite::InterpreterBuilder> pnca_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->dec2_pncas_model[layi]), *(fact->resolver));
        TFLITE_MINIMAL_CHECK(pnca_builder != nullptr);
        dec2_pncas_builder.push_back(std::move(pnca_builder));
    }

    dec2_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->dec2_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(dec2_builder != nullptr);
    post_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->post_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(post_builder != nullptr);
    post0_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->post0_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(post0_builder != nullptr);
    post1_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->post1_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(post1_builder != nullptr);
    post2_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->post2_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(post2_builder != nullptr);
    post3_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->post3_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(post3_builder != nullptr);
    dnorm_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->dnorm_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(dnorm_builder != nullptr);

    hifigan0_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan0_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan0_builder != nullptr);
    hifigan1_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan1_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan1_builder != nullptr);
    hifigan2_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan2_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan2_builder != nullptr);
    hifigan3_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan3_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan3_builder != nullptr);
    hifigan4_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan4_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan4_builder != nullptr);
    hifigan5_builder = std::make_shared<tflite::InterpreterBuilder>(*(fact->hifigan5_model), *(fact->resolver));
    TFLITE_MINIMAL_CHECK(hifigan5_builder != nullptr);

    std::cout<<"init model success\n";
}

stTTS::~stTTS(){}
stTTS::stTTS(std::string& model_path, std::string& model_fix,void (*pcm_callback)(std::vector<short> &pcm,void* args,bool endf),void*args)
     :_postdim(256),_meldim(82){
    _model = std::make_shared<TtsModel>(model_path,model_fix);

    tflite::InterpreterBuilder& _txtenc_builder = *(_model->txtenc_builder);
    _txtenc_builder(&txtenc_interpreter);
    TFLITE_MINIMAL_CHECK(txtenc_interpreter != nullptr);
    auto txtenc_sig_inputs = txtenc_interpreter->signature_inputs("serving_default");
    txtenc_interpreter->ResizeInputTensorStrict(txtenc_sig_inputs["text_in"],{1,10,4});
    TFLITE_MINIMAL_CHECK(txtenc_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _emot_builder = *(_model->emot_builder);
    _emot_builder(&emot_interpreter);
    TFLITE_MINIMAL_CHECK(emot_interpreter != nullptr);

    tflite::InterpreterBuilder& _varadp_builder = *(_model->varadp_builder);
    _varadp_builder(&varadp_interpreter);
    TFLITE_MINIMAL_CHECK(varadp_interpreter != nullptr);
    auto varadp_sig_inputs = varadp_interpreter->signature_inputs("serving_default");
    varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["txt_in"],{1,10,32});
    varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["emo_in"],{1,10,32});
    varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["spk_in"],{1,10,192});
    TFLITE_MINIMAL_CHECK(varadp_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _duration_builder = *(_model->duration_builder);
    _duration_builder(&duration_interpreter);
    TFLITE_MINIMAL_CHECK(duration_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(duration_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _LRtxt_builder = *(_model->LR_builder);
    _LRtxt_builder(&LRtxt_interpreter);
    TFLITE_MINIMAL_CHECK(LRtxt_interpreter != nullptr);
    tflite::InterpreterBuilder& _LRspk_builder = *(_model->LR_builder);
    _LRspk_builder(&LRspk_interpreter);
    TFLITE_MINIMAL_CHECK(LRspk_interpreter != nullptr);
    tflite::InterpreterBuilder& _LRemo_builder = *(_model->LR_builder);
    _LRemo_builder(&LRemo_interpreter);
    TFLITE_MINIMAL_CHECK(LRemo_interpreter != nullptr);
    tflite::InterpreterBuilder& _dursin_builder = *(_model->dursin_builder);
    _dursin_builder(&dursin_interpreter);
    TFLITE_MINIMAL_CHECK(dursin_interpreter != nullptr);
    tflite::InterpreterBuilder& _mem_builder = *(_model->mem_builder);
    _mem_builder(&mem_interpreter);
    TFLITE_MINIMAL_CHECK(mem_interpreter != nullptr);
    tflite::InterpreterBuilder& _attenH_builder = *(_model->attenH_builder);
    _attenH_builder(&attenH_interpreter);
    TFLITE_MINIMAL_CHECK(attenH_interpreter != nullptr);
    auto atth_sig_inputs = attenH_interpreter->signature_inputs("serving_default");
    attenH_interpreter->ResizeInputTensorStrict(atth_sig_inputs["mem_in"],{1,1,320});
    TFLITE_MINIMAL_CHECK(attenH_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _getmask_builder = *(_model->getmask_builder);
    _getmask_builder(&getmask_interpreter);
    TFLITE_MINIMAL_CHECK(getmask_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(getmask_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _dec1_builder = *(_model->dec1_builder);
    _dec1_builder(&dec1_interpreter);
    TFLITE_MINIMAL_CHECK(dec1_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(dec1_interpreter->AllocateTensors() == kTfLiteOk);

    for(int layi = 0;layi<_model->fact->_pnca_num;layi++){
        std::unique_ptr<tflite::Interpreter> pnca_interpreter;
        tflite::InterpreterBuilder& _pnca_builder = *(_model->dec2_pncas_builder[layi]);
        _pnca_builder(&pnca_interpreter);
        TFLITE_MINIMAL_CHECK(pnca_interpreter != nullptr);
        dec2_pncas_interpreter.push_back(std::move(pnca_interpreter));
    }

    tflite::InterpreterBuilder& _dec2_builder = *(_model->dec2_builder);
    _dec2_builder(&dec2_interpreter);
    TFLITE_MINIMAL_CHECK(dec2_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(dec2_interpreter->AllocateTensors() == kTfLiteOk);

    //auto dec2_sig_inputs = dec2_interpreter->signature_inputs("serving_default");
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["x_q_in"],{1,1,128});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["x_k_in"],{12,8,1,16});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["x_v_in"],{12,8,1,16});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["h_k_in"],{12,8,1,16});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["h_v_in"],{12,8,1,16});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["x_mask_in"],{1,1,1});
    //dec2_interpreter->ResizeInputTensorStrict(dec2_sig_inputs["h_mask_in"],{1,1,1});
    //TFLITE_MINIMAL_CHECK(dec2_interpreter->AllocateTensors() == kTfLiteOk);

    tflite::InterpreterBuilder& _post_builder = *(_model->post_builder);
    _post_builder(&post_interpreter);
    TFLITE_MINIMAL_CHECK(post_interpreter != nullptr);
    tflite::InterpreterBuilder& _post0_builder = *(_model->post0_builder);
    _post0_builder(&post0_interpreter);
    TFLITE_MINIMAL_CHECK(post0_interpreter != nullptr);
    tflite::InterpreterBuilder& _post1_builder = *(_model->post1_builder);
    _post1_builder(&post1_interpreter);
    TFLITE_MINIMAL_CHECK(post1_interpreter != nullptr);
    tflite::InterpreterBuilder& _post2_builder = *(_model->post2_builder);
    _post2_builder(&post2_interpreter);
    TFLITE_MINIMAL_CHECK(post2_interpreter != nullptr);
    tflite::InterpreterBuilder& _post3_builder = *(_model->post3_builder);
    _post3_builder(&post3_interpreter);
    TFLITE_MINIMAL_CHECK(post3_interpreter != nullptr);
    tflite::InterpreterBuilder& _dnorm_builder = *(_model->dnorm_builder);
    _dnorm_builder(&dnorm_interpreter);
    TFLITE_MINIMAL_CHECK(dnorm_interpreter != nullptr);

    tflite::InterpreterBuilder& _hifigan0_builder = *(_model->hifigan0_builder);
    _hifigan0_builder(&hifigan0_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan0_interpreter != nullptr);
    tflite::InterpreterBuilder& _hifigan1_builder = *(_model->hifigan1_builder);
    _hifigan1_builder(&hifigan1_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan1_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan1_interpreter->AllocateTensors() == kTfLiteOk);
    tflite::InterpreterBuilder& _hifigan2_builder = *(_model->hifigan2_builder);
    _hifigan2_builder(&hifigan2_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan2_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan2_interpreter->AllocateTensors() == kTfLiteOk);
    tflite::InterpreterBuilder& _hifigan3_builder = *(_model->hifigan3_builder);
    _hifigan3_builder(&hifigan3_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan3_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan3_interpreter->AllocateTensors() == kTfLiteOk);
    tflite::InterpreterBuilder& _hifigan4_builder = *(_model->hifigan4_builder);
    _hifigan4_builder(&hifigan4_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan4_interpreter != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan4_interpreter->AllocateTensors() == kTfLiteOk);
    tflite::InterpreterBuilder& _hifigan5_builder = *(_model->hifigan5_builder);
    _hifigan5_builder(&hifigan5_interpreter);
    TFLITE_MINIMAL_CHECK(hifigan5_interpreter != nullptr);

    //init();
    _pcm_callback = pcm_callback;
    _args = args;

}
void stTTS::init(){
    _endflag = false;
    _hifi1idx =_hifi1olp;
    _hifi2idx =_hifi2olp;
    _hifi3idx =_hifi3olp;
    _hifi4idx =_hifi4olp;
    _post0_idx = 0;
    _post_idx = 0;
    _post0_lpad.resize(1*37*_postdim,0.0);
    _post1_lpad.resize(1*37*_postdim,0.0);
    _post2_lpad.resize(1*37*_postdim,0.0);
    _post3_lpad.resize(1*37*_postdim,0.0);
    _post_ph.resize(128,0.0);
    _post_pc.resize(128,0.0);
    th_voc = std::make_shared<std::thread>(worker_vocoder,this);

}
void stTTS::clear(){
    _pad_memlen = 0;
    _postlen = 0;
    _hifi0len = 0;
    _hifi1len = 0;
    _hifi3len = 0;
    _hifi4len = 0;
    _dec2output.clear();
    _post0_lpad.clear();
    _post1_lpad.clear();
    _post2_lpad.clear();
    _post3_lpad.clear();
    _post_ph.clear();
    _post_pc.clear();
    _post0out.clear();
    _post1out.clear();
    _post2out.clear();
    _post3out.clear();
    _dnormout.clear();
    _hifi0out.clear();
    _exciout.clear();
    _hifi1out.clear();
    _hifi2out.clear();
    _hifi3out.clear();
    _hifi4out.clear();
    _pcm.clear();
    _pcmlen = 0;
}
bool stTTS::get_sent_ids(const std::vector<std::vector<std::string>> &sent, std::vector<std::vector<int>> &sentid)
{
    bool valid = true;
    std::vector<int> syids;
    std::vector<int> toneids;
    std::vector<int> syflagids;
    std::vector<int> wsids;
    std::vector<int> emoids;
    for(int wid = 0;wid<sent.size();wid++){
        std::vector<string> word = sent[wid];
        if (word.size() < 6){
            valid = false;
            std::cout<<__LINE__<<std::endl;
            break;
        }
        auto syitem = g_sy_to_id.find("@"+word[0]);
        if (syitem != g_sy_to_id.end()){
            syids.push_back(syitem->second);
        }else{
            std::cout<<__LINE__<<std::endl;
            valid = false;
            break;
        }

        auto toneitem = g_tone_to_id.find(word[1]);
        if (toneitem != g_tone_to_id.end()){
            toneids.push_back(toneitem->second);
        }else{
            std::cout<<__LINE__<<std::endl;
            valid = false;
            break;
        }

        auto syflagitem = g_syllable_flag_to_id.find(word[2]);
        if (syflagitem != g_syllable_flag_to_id.end()){
            syflagids.push_back(syflagitem->second);
        }else{
            std::cout<<__LINE__<<std::endl;
            valid = false;
            break;
        }
        auto wsitem = g_word_segment_to_id.find(word[3]);
        if (wsitem != g_word_segment_to_id.end()){
            wsids.push_back(wsitem->second);
        }else{
            std::cout<<__LINE__<<std::endl;
            valid = false;
            break;
        }
        auto emoitem = g_emo_category_to_id.find(word[4]);
        if (emoitem != g_emo_category_to_id.end()){
            emoids.push_back(emoitem->second);
        }else{
            std::cout<<__LINE__<<std::endl;
            valid = false;
            break;
        }

    }
    if (valid){
        sentid.push_back(std::move(syids));
        sentid.push_back(std::move(toneids));
        sentid.push_back(std::move(syflagids));
        sentid.push_back(std::move(wsids));
        sentid.push_back(std::move(emoids));
    }else{
        std::cout<<"invalid sentences"<<std::endl;
    }
    return valid;
}
//void th_voc(stTTS *ttsobj){
//    while(true){
//        {
//            const std::lock_guard<std::mutex> lock(end_mutex_);
//
//            if (_endflag) {
//                _stDecoder->decode(true,true);
//                break;
//            }
//        }
//        _stDecoder->decode(true);
//    }
//}
void stTTS::input_txt(const std::vector<std::vector<std::vector<std::string>>> &sentences){

    _start = std::chrono::steady_clock::now();
    for (int sentid =0; sentid<sentences.size(); sentid++){
        const std::vector<std::vector<std::string>> &sent = sentences[sentid];
        std::vector<std::vector<int>> sentids;
        bool valid = get_sent_ids(sent,sentids);
        if (!valid || sentids.size() == 0){ 
            break;
        }
        _pcmid += 1;
        //std::thread worker_voc(th_voc, this);
        init();

        auto txtenc_sig_inputs = txtenc_interpreter->signature_inputs("serving_default");
        txtenc_interpreter->ResizeInputTensorStrict(txtenc_sig_inputs["text_in"],{1,int(sentids[0].size()),4});
        TFLITE_MINIMAL_CHECK(txtenc_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* text_in = txtenc_interpreter->input_tensor_by_signature("text_in","serving_default");
        TFLITE_MINIMAL_CHECK(text_in != nullptr);
        for(int i=0;i<sentids[0].size();i++){
            *(text_in->data.i32+i*4) = sentids[0][i];
            *(text_in->data.i32+i*4 + 1) = sentids[1][i];
            *(text_in->data.i32+i*4 + 2) = sentids[2][i];
            *(text_in->data.i32+i*4 + 3) = sentids[3][i];
        }
        txtenc_interpreter->Invoke();
        const TfLiteTensor* txtenc_out = txtenc_interpreter->output_tensor_by_signature("text_fft_encoder", "serving_default");
        TFLITE_MINIMAL_CHECK(txtenc_out != nullptr);
        DBGptime()

        auto emot_sig_inputs = emot_interpreter->signature_inputs("serving_default");
        emot_interpreter->ResizeInputTensorStrict(emot_sig_inputs["args_0"],{1,int(sentids[4].size())});
        TFLITE_MINIMAL_CHECK(emot_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* emot_in = emot_interpreter->input_tensor_by_signature("args_0","serving_default");
        TFLITE_MINIMAL_CHECK(emot_in != nullptr);
        memcpy(emot_in->data.i32,sentids[4].data(),sentids[4].size()*sizeof(int));
        emot_interpreter->Invoke();
        const TfLiteTensor* emot_out = emot_interpreter->output_tensor_by_signature("emot_emd", "serving_default");
        TFLITE_MINIMAL_CHECK(emot_out != nullptr);
        TFLITE_MINIMAL_CHECK(txtenc_out != nullptr);
        DBGptime()

        auto varadp_sig_inputs = varadp_interpreter->signature_inputs("serving_default");
        varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["txt_in"],{1,txtenc_out->dims->data[1],txtenc_out->dims->data[2]});
        varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["emo_in"],{1,emot_out->dims->data[1],emot_out->dims->data[2]});
        varadp_interpreter->ResizeInputTensorStrict(varadp_sig_inputs["spk_in"],{1,txtenc_out->dims->data[1],192});
        TFLITE_MINIMAL_CHECK(varadp_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* txt_in = varadp_interpreter->input_tensor_by_signature("txt_in","serving_default");
        TfLiteTensor* spk_in = varadp_interpreter->input_tensor_by_signature("spk_in","serving_default");
        TfLiteTensor* emo_in = varadp_interpreter->input_tensor_by_signature("emo_in","serving_default");
        TFLITE_MINIMAL_CHECK(txt_in != nullptr);
        TFLITE_MINIMAL_CHECK(spk_in != nullptr);
        TFLITE_MINIMAL_CHECK(emo_in != nullptr);
        memcpy(txt_in->data.f,txtenc_out->data.f,txtenc_out->dims->data[1]*txtenc_out->dims->data[2]*sizeof(float));
        memcpy(emo_in->data.f,emot_out->data.f,emot_out->dims->data[1]*emot_out->dims->data[2]*sizeof(float));
        for(int i=0;i<txtenc_out->dims->data[1];i++){
            memcpy(spk_in->data.f + i*192,_model->fact->spk_embedding.data(),_model->fact->spk_embedding.size()*sizeof(float));
        }
        varadp_interpreter->Invoke();
        const TfLiteTensor* txt_emb_aug = varadp_interpreter->output_tensor_by_signature("variance_adaptor1", "serving_default");
        TFLITE_MINIMAL_CHECK(txt_emb_aug != nullptr);
        const TfLiteTensor* pred_con = varadp_interpreter->output_tensor_by_signature("variance_adaptor1_1", "serving_default");
        TFLITE_MINIMAL_CHECK(pred_con != nullptr);
        DBGptime()

        TfLiteTensor* cond_in = duration_interpreter->input_tensor_by_signature("cond","serving_default");
        TfLiteTensor* durtxt_in = duration_interpreter->input_tensor_by_signature("txt_in","serving_default");
        TfLiteTensor* dur_h0 = duration_interpreter->input_tensor_by_signature("p_h0","serving_default");
        TfLiteTensor* dur_c0 = duration_interpreter->input_tensor_by_signature("p_c0","serving_default");
        TfLiteTensor* dur_h1 = duration_interpreter->input_tensor_by_signature("p_h1","serving_default");
        TfLiteTensor* dur_c1 = duration_interpreter->input_tensor_by_signature("p_c1","serving_default");
        TFLITE_MINIMAL_CHECK(cond_in != nullptr);
        TFLITE_MINIMAL_CHECK(durtxt_in != nullptr);
        TFLITE_MINIMAL_CHECK(dur_h0 != nullptr);
        TFLITE_MINIMAL_CHECK(dur_c0 != nullptr);
        TFLITE_MINIMAL_CHECK(dur_h1 != nullptr);
        TFLITE_MINIMAL_CHECK(dur_c1 != nullptr);
        memset(durtxt_in->data.f,0,durtxt_in->dims->data[1]*durtxt_in->dims->data[2]*sizeof(float));
        memset(dur_h0->data.f,0,dur_h0->dims->data[0]*dur_h0->dims->data[1]*sizeof(float));
        memset(dur_c0->data.f,0,dur_c0->dims->data[0]*dur_c0->dims->data[1]*sizeof(float));
        memset(dur_h1->data.f,0,dur_h1->dims->data[0]*dur_h1->dims->data[1]*sizeof(float));
        memset(dur_c1->data.f,0,dur_c1->dims->data[0]*dur_c1->dims->data[1]*sizeof(float));
        std::vector<float> duration_prediction;
        for (int i=0;i<pred_con->dims->data[1];i++){
            memcpy(cond_in->data.f, pred_con->data.f+i*pred_con->dims->data[2],pred_con->dims->data[2]*sizeof(float));
            duration_interpreter->Invoke();

            const TfLiteTensor* durout_x = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor", "serving_default");
            const TfLiteTensor* durout_h0 = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor_1", "serving_default");
            const TfLiteTensor* durout_c0 = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor_2", "serving_default");
            const TfLiteTensor* durout_h1 = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor_3", "serving_default");
            const TfLiteTensor* durout_c1 = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor_4", "serving_default");
            const TfLiteTensor* durout_logx = duration_interpreter->output_tensor_by_signature("var_rnn_ar_predictor_5", "serving_default");
            TFLITE_MINIMAL_CHECK(durout_x != nullptr);
            TFLITE_MINIMAL_CHECK(durout_h0 != nullptr);
            TFLITE_MINIMAL_CHECK(durout_c0 != nullptr);
            TFLITE_MINIMAL_CHECK(durout_h1 != nullptr);
            TFLITE_MINIMAL_CHECK(durout_c1 != nullptr);
            TFLITE_MINIMAL_CHECK(durout_logx != nullptr);
            memcpy(durtxt_in->data.f,durout_x->data.f,durtxt_in->dims->data[1]*durtxt_in->dims->data[2]*sizeof(float));
            memcpy(dur_h0->data.f,durout_h0->data.f,dur_h0->dims->data[0]*dur_h0->dims->data[1]*sizeof(float));
            memcpy(dur_c0->data.f,durout_c0->data.f,dur_c0->dims->data[0]*dur_c0->dims->data[1]*sizeof(float));
            memcpy(dur_h1->data.f,durout_h1->data.f,dur_h1->dims->data[0]*dur_h1->dims->data[1]*sizeof(float));
            memcpy(dur_c1->data.f,durout_c1->data.f,dur_c1->dims->data[0]*dur_c1->dims->data[1]*sizeof(float));
            duration_prediction.insert(duration_prediction.end(),durout_logx->data.f,durout_logx->data.f+durout_logx->dims->data[1]*durout_logx->dims->data[2]);
        }
        DBGptime()

        auto LRtxt_sig_inputs = LRtxt_interpreter->signature_inputs("serving_default");
        LRtxt_interpreter->ResizeInputTensorStrict(LRtxt_sig_inputs["lr_inputs"],{1,txtenc_out->dims->data[1],txtenc_out->dims->data[2]});
        LRtxt_interpreter->ResizeInputTensorStrict(LRtxt_sig_inputs["duration_pred"],{1,pred_con->dims->data[1],1});
        TFLITE_MINIMAL_CHECK(LRtxt_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* lrin_txt = LRtxt_interpreter->input_tensor_by_signature("lr_inputs","serving_default");
        TfLiteTensor* lrintxt_dura = LRtxt_interpreter->input_tensor_by_signature("duration_pred","serving_default");
        memcpy(lrin_txt->data.f,txt_emb_aug->data.f,txt_emb_aug->dims->data[1]*txt_emb_aug->dims->data[2]*sizeof(float));
        memcpy(lrintxt_dura->data.f,duration_prediction.data(),pred_con->dims->data[1]*sizeof(float));
        LRtxt_interpreter->Invoke();
        const TfLiteTensor* lrout_txt = LRtxt_interpreter->output_tensor_by_signature("length_regulator", "serving_default");
        const TfLiteTensor* lrout_txtlen = LRtxt_interpreter->output_tensor_by_signature("length_regulator_1", "serving_default");
        _pad_memlen = lrout_txt->dims->data[1] - *(lrout_txtlen->data.i32);
        DBGptime()

        auto LRemo_sig_inputs = LRemo_interpreter->signature_inputs("serving_default");
        LRemo_interpreter->ResizeInputTensorStrict(LRemo_sig_inputs["lr_inputs"],{1,emot_out->dims->data[1],emot_out->dims->data[2]});
        LRemo_interpreter->ResizeInputTensorStrict(LRemo_sig_inputs["duration_pred"],{1,pred_con->dims->data[1],1});
        TFLITE_MINIMAL_CHECK(LRemo_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* lrin_emo = LRemo_interpreter->input_tensor_by_signature("lr_inputs","serving_default");
        TfLiteTensor* lrinemo_dura = LRemo_interpreter->input_tensor_by_signature("duration_pred","serving_default");
        memcpy(lrin_emo->data.f,emot_out->data.f,emot_out->dims->data[1]*emot_out->dims->data[2]*sizeof(float));
        memcpy(lrinemo_dura->data.f,duration_prediction.data(),pred_con->dims->data[1]*sizeof(float));
        LRemo_interpreter->Invoke();
        const TfLiteTensor* lrout_emot = LRemo_interpreter->output_tensor_by_signature("length_regulator", "serving_default");

        auto LRspk_sig_inputs = LRspk_interpreter->signature_inputs("serving_default");
        LRspk_interpreter->ResizeInputTensorStrict(LRspk_sig_inputs["lr_inputs"],{1,txtenc_out->dims->data[1],192});
        LRspk_interpreter->ResizeInputTensorStrict(LRspk_sig_inputs["duration_pred"],{1,pred_con->dims->data[1],1});
        TFLITE_MINIMAL_CHECK(LRspk_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* lrin_spk = LRspk_interpreter->input_tensor_by_signature("lr_inputs","serving_default");
        TfLiteTensor* lrinspk_dura = LRspk_interpreter->input_tensor_by_signature("duration_pred","serving_default");
        for(int i=0;i<txtenc_out->dims->data[1];i++){
            memcpy(lrin_spk->data.f + i*192,_model->fact->spk_embedding.data(),_model->fact->spk_embedding.size()*sizeof(float));
        }
        memcpy(lrinspk_dura->data.f,duration_prediction.data(),pred_con->dims->data[1]*sizeof(float));
        LRspk_interpreter->Invoke();
        const TfLiteTensor* lrout_spk = LRspk_interpreter->output_tensor_by_signature("length_regulator", "serving_default");

        auto dursin_sig_inputs = dursin_interpreter->signature_inputs("serving_default");
        dursin_interpreter->ResizeInputTensorStrict(dursin_sig_inputs["lr_txt_in"],{1,lrout_txt->dims->data[1],lrout_txt->dims->data[2]});
        dursin_interpreter->ResizeInputTensorStrict(dursin_sig_inputs["duration_pred"],{1,pred_con->dims->data[1],1});
        TFLITE_MINIMAL_CHECK(dursin_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* dursinin_txt = dursin_interpreter->input_tensor_by_signature("lr_txt_in","serving_default");
        TfLiteTensor* dursinin_dura = dursin_interpreter->input_tensor_by_signature("duration_pred","serving_default");
        memcpy(dursinin_txt->data.f,lrout_txt->data.f,lrout_txt->dims->data[1]*lrout_txt->dims->data[2]*sizeof(float));
        memcpy(dursinin_dura->data.f,duration_prediction.data(),pred_con->dims->data[1]*sizeof(float));
        dursin_interpreter->Invoke();
        const TfLiteTensor* dursinout_txt = dursin_interpreter->output_tensor_by_signature("dur_sinusoidal_position_encoder", "serving_default");

        auto mem_sig_inputs = mem_interpreter->signature_inputs("serving_default");
        mem_interpreter->ResizeInputTensorStrict(mem_sig_inputs["txt_in"],{1,dursinout_txt->dims->data[1],dursinout_txt->dims->data[2]});
        mem_interpreter->ResizeInputTensorStrict(mem_sig_inputs["spk_in"],{1,lrout_spk->dims->data[1],lrout_spk->dims->data[2]});
        mem_interpreter->ResizeInputTensorStrict(mem_sig_inputs["emo_in"],{1,lrout_emot->dims->data[1],lrout_emot->dims->data[2]});
        TFLITE_MINIMAL_CHECK(mem_interpreter->AllocateTensors() == kTfLiteOk);
        TfLiteTensor* memin_txt = mem_interpreter->input_tensor_by_signature("txt_in","serving_default");
        TfLiteTensor* memin_spk = mem_interpreter->input_tensor_by_signature("spk_in","serving_default");
        TfLiteTensor* memin_emo = mem_interpreter->input_tensor_by_signature("emo_in","serving_default");
        memcpy(memin_txt->data.f,dursinout_txt->data.f,dursinout_txt->dims->data[1]*lrout_txt->dims->data[2]*sizeof(float));
        memcpy(memin_spk->data.f,lrout_spk->data.f,lrout_spk->dims->data[1]*lrout_spk->dims->data[2]*sizeof(float));
        memcpy(memin_emo->data.f,lrout_emot->data.f,lrout_emot->dims->data[1]*lrout_emot->dims->data[2]*sizeof(float));
        mem_interpreter->Invoke();
        const TfLiteTensor* memout_txt = mem_interpreter->output_tensor_by_signature("txtmem", "serving_default");
        
        int dur_max = (*std::max_element(duration_prediction.begin(),duration_prediction.end()))/3+0.5;
        DBGptime()
        am_dec(memout_txt->data.f,memout_txt->dims->data[1],memout_txt->dims->data[2],dur_max);
        clear();
    }
    _pcm_callback(_pcm,_args,true);

    return;
}
void stTTS::am_dec(float *memdata, int memlen,int memdim, int durmax){
    if (memlen <= 0){
         _endflag = true;
         //set end first
         _vocsmp.Signal();
         th_voc->join();
         return;
    }
    auto atth_sig_inputs = attenH_interpreter->signature_inputs("serving_default");
    attenH_interpreter->ResizeInputTensorStrict(atth_sig_inputs["mem_in"],{1,memlen,memdim});
    TFLITE_MINIMAL_CHECK(attenH_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* atth_in = attenH_interpreter->input_tensor_by_signature("mem_in","serving_default");
    memcpy(atth_in->data.f,memdata,memlen*memdim*sizeof(float));
    attenH_interpreter->Invoke();
    const TfLiteTensor* atthout_k = attenH_interpreter->output_tensor_by_signature("hybrid_attention_decoder_h", "serving_default");
    const TfLiteTensor* atthout_v = attenH_interpreter->output_tensor_by_signature("hybrid_attention_decoder_h_1", "serving_default");
    int attenH_len = atthout_k->dims->data[2];
    DBGptime()

    auto mask_sig_inputs = getmask_interpreter->signature_inputs("serving_default");
    TfLiteTensor* maskin_max = getmask_interpreter->input_tensor_by_signature("max_in","serving_default");
    TfLiteTensor* maskin_x = getmask_interpreter->input_tensor_by_signature("x_in","serving_default");
    TfLiteTensor* maskin_h = getmask_interpreter->input_tensor_by_signature("h_in","serving_default");
    *(maskin_max->data.i32) = memlen;
    *(maskin_x->data.i32) = durmax;
    *(maskin_h->data.i32) = durmax;
    getmask_interpreter->Invoke();
    const TfLiteTensor* x_mask = getmask_interpreter->output_tensor_by_signature("getmask", "serving_default");
    const TfLiteTensor* h_mask = getmask_interpreter->output_tensor_by_signature("getmask_1", "serving_default");

    auto dec1_sig_inputs = dec1_interpreter->signature_inputs("serving_default");
    TfLiteTensor* dec1in_mel = dec1_interpreter->input_tensor_by_signature("mel_in","serving_default");
    TfLiteTensor* dec1in_mem = dec1_interpreter->input_tensor_by_signature("mem_in","serving_default");
    memset(dec1in_mel->data.f, 0, dec1in_mel->dims->data[2]*sizeof(float));
    memcpy(dec1in_mem->data.f, memdata, dec1in_mem->dims->data[2]*sizeof(float));


    for(int layi=0;layi<_model->fact->_pnca_num;layi++){
        auto dec2_sig_inputs = dec2_pncas_interpreter[layi]->signature_inputs("serving_default");
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_q_in"],{1,1,128});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_k_in"],{1,8,1,16});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_v_in"],{1,8,1,16});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_k_in"],{1,8,attenH_len,16});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_v_in"],{1,8,attenH_len,16});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_mask_in"],{1,1,1});
        dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_mask_in"],{1,1,h_mask->dims->data[2]});
        TFLITE_MINIMAL_CHECK(dec2_pncas_interpreter[layi]->AllocateTensors() == kTfLiteOk);

        TfLiteTensor* dec2in_xk = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_k_in","serving_default");
        TfLiteTensor* dec2in_xv = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_v_in","serving_default");
        TfLiteTensor* dec2in_hk = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_k_in","serving_default");
        TfLiteTensor* dec2in_hv = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_v_in","serving_default");
        TfLiteTensor* dec2in_xmask = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_mask_in","serving_default");
        TfLiteTensor* dec2in_hmask = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_mask_in","serving_default");
        TFLITE_MINIMAL_CHECK(dec2in_xk != nullptr);
        TFLITE_MINIMAL_CHECK(dec2in_xv != nullptr);
        TFLITE_MINIMAL_CHECK(dec2in_hk != nullptr);
        TFLITE_MINIMAL_CHECK(dec2in_hv != nullptr);
        TFLITE_MINIMAL_CHECK(dec2in_xmask != nullptr);
        TFLITE_MINIMAL_CHECK(dec2in_hmask != nullptr);
        memset(dec2in_xk->data.f,0,(8*1*16)*sizeof(float));
        memset(dec2in_xv->data.f,0,(8*1*16)*sizeof(float));
        memcpy(dec2in_hk->data.f,atthout_k->data.f+(layi*8*attenH_len*16),8*attenH_len*16*sizeof(float));
        memcpy(dec2in_hv->data.f,atthout_v->data.f+(layi*8*attenH_len*16),8*attenH_len*16*sizeof(float));
        memcpy(dec2in_xmask->data.b,x_mask->data.b,sizeof(bool));
        memcpy(dec2in_hmask->data.b,h_mask->data.b,h_mask->dims->data[2]*sizeof(bool));
    }
    DBGptime()
    for(int mi=0;mi<memlen;mi++){
        dec1_interpreter->Invoke();
        const TfLiteTensor* dec1out = dec1_interpreter->output_tensor_by_signature("hybrid_attention_decoder_1", "serving_default");
        DBGptime()

        float *pnca_in = dec1out->data.f;
        std::vector<std::vector<float>> tmp_xk_a;
        std::vector<std::vector<float>> tmp_xv_a;
        int outxk_len;
        for(int layi=0;layi<_model->fact->_pnca_num;layi++){
            TfLiteTensor* dec2in_xq = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_q_in","serving_default");
            TFLITE_MINIMAL_CHECK(dec2in_xq != nullptr);
            memcpy(dec2in_xq->data.f, pnca_in, dec2in_xq->dims->data[2]*sizeof(float));
            dec2_pncas_interpreter[layi]->Invoke();
            std::string dec2outname("dec2pnca_");
            dec2outname += std::to_string(layi);
            const TfLiteTensor* dec2pnca_out = dec2_pncas_interpreter[layi]->output_tensor_by_signature(dec2outname.c_str(), "serving_default");
            TFLITE_MINIMAL_CHECK(dec2pnca_out != nullptr);
            const TfLiteTensor* dec2out_xk = dec2_pncas_interpreter[layi]->output_tensor_by_signature((dec2outname + "_1").c_str(), "serving_default");
            TFLITE_MINIMAL_CHECK(dec2out_xk != nullptr);
            const TfLiteTensor* dec2out_xv = dec2_pncas_interpreter[layi]->output_tensor_by_signature((dec2outname + "_2").c_str(), "serving_default");
            TFLITE_MINIMAL_CHECK(dec2out_xv != nullptr);
            pnca_in = dec2pnca_out->data.f;
            outxk_len = dec2out_xk->dims->data[2];
            std::vector<float> tmp_xk(dec2out_xk->data.f,dec2out_xk->data.f + 8*outxk_len*16);
            std::vector<float> tmp_xv(dec2out_xv->data.f,dec2out_xv->data.f + 8*outxk_len*16);
            tmp_xk_a.push_back(std::move(tmp_xk));
            tmp_xv_a.push_back(std::move(tmp_xv));
        }
        TfLiteTensor* dec2_pnca_in = dec2_interpreter->input_tensor_by_signature("pnca_in","serving_default");
        TFLITE_MINIMAL_CHECK(dec2_pnca_in != nullptr);
        memcpy(dec2_pnca_in->data.f, pnca_in, dec2_pnca_in->dims->data[2]*sizeof(float));
        dec2_interpreter->Invoke();
        const TfLiteTensor* dec2out = dec2_interpreter->output_tensor_by_signature("hybrid_attention_decoder_2", "serving_default");
        TFLITE_MINIMAL_CHECK(dec2out != nullptr);
        DBGptime()
        _dec_mutex.lock();
        _dec2output.insert(_dec2output.end(),dec2out->data.f,dec2out->data.f+dec2out->dims->data[2]);
        _dec_mutex.unlock();

        if (mi<memlen-1){
            //am_post(false);
            _vocsmp.Signal();

            memcpy(dec1in_mel->data.f,dec2out->data.f+dec2out->dims->data[2]-dec1in_mel->dims->data[2],dec1in_mel->dims->data[2]*sizeof(float));
            memcpy(dec1in_mem->data.f, memdata + (mi+1)*memdim, dec1in_mem->dims->data[2]*sizeof(float));

            for(int layi=0;layi<_model->fact->_pnca_num;layi++){
                auto dec2_sig_inputs = dec2_pncas_interpreter[layi]->signature_inputs("serving_default");
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_q_in"],{1,1,128});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_k_in"],{1,8,outxk_len,16});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_v_in"],{1,8,outxk_len,16});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_k_in"],{1,8,attenH_len,16});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_v_in"],{1,8,attenH_len,16});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["x_mask_in"],{1,1,mi+2});
                dec2_pncas_interpreter[layi]->ResizeInputTensorStrict(dec2_sig_inputs["h_mask_in"],{1,1,h_mask->dims->data[2]});
                TFLITE_MINIMAL_CHECK(dec2_pncas_interpreter[layi]->AllocateTensors() == kTfLiteOk);
                TfLiteTensor* dec2in_xk = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_k_in","serving_default");
                TfLiteTensor* dec2in_xv = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_v_in","serving_default");
                TfLiteTensor* dec2in_hk = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_k_in","serving_default");
                TfLiteTensor* dec2in_hv = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_v_in","serving_default");
                TfLiteTensor* dec2in_xmask = dec2_pncas_interpreter[layi]->input_tensor_by_signature("x_mask_in","serving_default");
                TfLiteTensor* dec2in_hmask = dec2_pncas_interpreter[layi]->input_tensor_by_signature("h_mask_in","serving_default");

                memcpy(dec2in_xk->data.f,tmp_xk_a[layi].data(),8*outxk_len*16*sizeof(float));
                memcpy(dec2in_xv->data.f,tmp_xv_a[layi].data(),8*outxk_len*16*sizeof(float));
                memcpy(dec2in_hk->data.f,atthout_k->data.f+(layi*8*attenH_len*16),8*attenH_len*16*sizeof(float));
                memcpy(dec2in_hv->data.f,atthout_v->data.f+(layi*8*attenH_len*16),8*attenH_len*16*sizeof(float));
                memcpy(dec2in_xmask->data.b,x_mask->data.b + (mi+1)*x_mask->dims->data[2],(mi+2)*sizeof(bool));
                memcpy(dec2in_hmask->data.b,h_mask->data.b + (mi+1)*h_mask->dims->data[2],h_mask->dims->data[2]*sizeof(bool));
            }
        }else{
            //am_post(true);
            _endflag = true;
            //set end first
            _vocsmp.Signal();
            th_voc->join();
        }
    }
}
#define  AM_POST_PROC(post_interpreter,inputs,lpad,outputs,out1,out2) \
{\
    int postin_len = inputs.size()/_postdim;\
    if (!end){\
        if (postin_len < 6) return false;\
    }else{\
        if (postin_len == 0) return true;\
    }\
    auto post_sig_inputs = post_interpreter->signature_inputs("serving_default");\
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["post_in"],{1,postin_len,_postdim});\
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["mask"],{1,postin_len,1});\
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["lpadding"],{1,37,_postdim});\
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["rpadding"],{1,3,_postdim});\
    TFLITE_MINIMAL_CHECK(post_interpreter->AllocateTensors() == kTfLiteOk);\
    TfLiteTensor* postin = post_interpreter->input_tensor_by_signature("post_in","serving_default");\
    TFLITE_MINIMAL_CHECK(postin != nullptr);\
    TfLiteTensor* postin_mask = post_interpreter->input_tensor_by_signature("mask","serving_default");\
    TFLITE_MINIMAL_CHECK(postin_mask != nullptr);\
    TfLiteTensor* postin_lpad = post_interpreter->input_tensor_by_signature("lpadding","serving_default");\
    TFLITE_MINIMAL_CHECK(postin_lpad != nullptr);\
    TfLiteTensor* postin_rpad = post_interpreter->input_tensor_by_signature("rpadding","serving_default");\
    TFLITE_MINIMAL_CHECK(postin_rpad != nullptr);\
    memcpy(postin->data.f,inputs.data(), postin_len*_postdim*sizeof(float));\
    memset(postin_mask->data.b,1,postin_len*sizeof(bool));\
    if (end && _pad_memlen > 0 && postin_len > _pad_memlen){\
        memset(postin_mask->data.b+(postin_len-_pad_memlen),0,_pad_memlen*sizeof(bool));\
    }\
    memcpy(postin_lpad->data.f,lpad.data(),1*37*_postdim*sizeof(float));\
    memset(postin_rpad->data.f,0,1*3*_postdim*sizeof(float));\
    post_interpreter->Invoke();\
    const TfLiteTensor* postout = post_interpreter->output_tensor_by_signature(out1, "serving_default");\
    TFLITE_MINIMAL_CHECK(postout != nullptr);\
    const TfLiteTensor* postout_mem = post_interpreter->output_tensor_by_signature(out2, "serving_default");\
    TFLITE_MINIMAL_CHECK(postout_mem != nullptr);\
    int postlen = postout->dims->data[1];\
    if (!end){\
        postlen -= 3;\
        lpad.insert(lpad.end(),postout_mem->data.f,postout_mem->data.f+postlen*_postdim);\
        lpad.erase(lpad.begin(),lpad.begin() + postlen*_postdim);\
    }\
    outputs.insert(outputs.end(),postout->data.f,postout->data.f+postlen*_postdim);\
    inputs.erase(inputs.begin(),inputs.begin()+postlen*_postdim);\
}
bool stTTS::am_post(){
    _vocsmp.Wait();

    int declen = _dec2output.size()/_meldim - _post0_idx;
    bool end = _endflag;
    int post0in_len = declen;
    if (!end){
        if (declen < 6) return false;
    }else{
        if (declen == 0) return true;
    }
    DBGprint("declen",declen)
    auto post0_sig_inputs = post0_interpreter->signature_inputs("serving_default");
    post0_interpreter->ResizeInputTensorStrict(post0_sig_inputs["post_in"],{1,post0in_len,_meldim});
    post0_interpreter->ResizeInputTensorStrict(post0_sig_inputs["mask"],{1,post0in_len,1});
    post0_interpreter->ResizeInputTensorStrict(post0_sig_inputs["lpadding"],{1,37,_postdim});
    post0_interpreter->ResizeInputTensorStrict(post0_sig_inputs["rpadding"],{1,3,_postdim});
    TFLITE_MINIMAL_CHECK(post0_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* post0in = post0_interpreter->input_tensor_by_signature("post_in","serving_default");
    TFLITE_MINIMAL_CHECK(post0in != nullptr);
    TfLiteTensor* post0in_mask = post0_interpreter->input_tensor_by_signature("mask","serving_default");
    TFLITE_MINIMAL_CHECK(post0in_mask != nullptr);
    TfLiteTensor* post0in_lpad = post0_interpreter->input_tensor_by_signature("lpadding","serving_default");
    TFLITE_MINIMAL_CHECK(post0in_lpad != nullptr);
    TfLiteTensor* post0in_rpad = post0_interpreter->input_tensor_by_signature("rpadding","serving_default");
    TFLITE_MINIMAL_CHECK(post0in_rpad != nullptr);

    _dec_mutex.lock();
    memcpy(post0in->data.f,_dec2output.data()+_post0_idx*_meldim, post0in_len*_meldim*sizeof(float));
    _dec_mutex.unlock();

    memset(post0in_mask->data.b,1,post0in_len*sizeof(bool));
    if (end && _pad_memlen > 0 && post0in_len > _pad_memlen){
        memset(post0in_mask->data.b+(post0in_len-_pad_memlen),0,_pad_memlen*sizeof(bool));
    }

    memcpy(post0in_lpad->data.f,_post0_lpad.data(),1*37*_postdim*sizeof(float));
    memset(post0in_rpad->data.f,0,1*3*_postdim*sizeof(float));
    post0_interpreter->Invoke();
    const TfLiteTensor* post0out = post0_interpreter->output_tensor_by_signature("post_net0", "serving_default");
    TFLITE_MINIMAL_CHECK(post0out != nullptr);
    const TfLiteTensor* post0out_mem = post0_interpreter->output_tensor_by_signature("post_net0_1", "serving_default");
    TFLITE_MINIMAL_CHECK(post0out_mem != nullptr);
    int post0len = post0out->dims->data[1];
    if (!end){
        post0len -= 3;
        _post0_lpad.insert(_post0_lpad.end(),post0out_mem->data.f,post0out_mem->data.f+post0len*_postdim);
        _post0_lpad.erase(_post0_lpad.begin(),_post0_lpad.begin() + post0len*_postdim);
    }
    _post0out.insert(_post0out.end(),post0out->data.f,post0out->data.f+post0len*_postdim);
    _post0_idx += post0len;

    AM_POST_PROC(post1_interpreter,_post0out,_post1_lpad,_post1out,"post_net1","post_net1_1") 
    AM_POST_PROC(post2_interpreter,_post1out,_post2_lpad,_post2out,"post_net2","post_net2_1") 
    AM_POST_PROC(post3_interpreter,_post2out,_post3_lpad,_post3out,"post_net3","post_net3_1") 

    int postin_len = _post3out.size()/_postdim;
    auto post_sig_inputs = post_interpreter->signature_inputs("serving_default");
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["post_in"],{1,postin_len,_postdim});
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["p_h"],{1,128});
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["p_c"],{1,128});
    post_interpreter->ResizeInputTensorStrict(post_sig_inputs["post_res"],{1,postin_len,_meldim});
    TFLITE_MINIMAL_CHECK(post_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* postin = post_interpreter->input_tensor_by_signature("post_in","serving_default");
    TFLITE_MINIMAL_CHECK(postin != nullptr);
    TfLiteTensor* postin_ph = post_interpreter->input_tensor_by_signature("p_h","serving_default");
    TFLITE_MINIMAL_CHECK(postin_ph != nullptr);
    TfLiteTensor* postin_pc = post_interpreter->input_tensor_by_signature("p_c","serving_default");
    TFLITE_MINIMAL_CHECK(postin_pc != nullptr);
    TfLiteTensor* postin_res = post_interpreter->input_tensor_by_signature("post_res","serving_default");
    TFLITE_MINIMAL_CHECK(postin_res != nullptr);
    memcpy(postin->data.f,_post3out.data(), postin_len*_postdim*sizeof(float));
    memcpy(postin_ph->data.f,_post_ph.data(), 128*sizeof(float));
    memcpy(postin_pc->data.f,_post_pc.data(), 128*sizeof(float));
    _dec_mutex.lock();
    memcpy(postin_res->data.f,_dec2output.data()+(_post_idx*_meldim), postin_len*_meldim*sizeof(float));
    _dec_mutex.unlock();
    post_interpreter->Invoke();
    const TfLiteTensor* postout = post_interpreter->output_tensor_by_signature("post_net", "serving_default");
    TFLITE_MINIMAL_CHECK(postout != nullptr);
    const TfLiteTensor* postout_ph = post_interpreter->output_tensor_by_signature("post_net_1", "serving_default");
    TFLITE_MINIMAL_CHECK(postout_ph != nullptr);
    const TfLiteTensor* postout_pc = post_interpreter->output_tensor_by_signature("post_net_2", "serving_default");
    TFLITE_MINIMAL_CHECK(postout_pc != nullptr);
    memcpy(_post_ph.data(), postout_ph->data.f,128*sizeof(float));
    memcpy(_post_pc.data(), postout_pc->data.f,128*sizeof(float));
    int postlen = postout->dims->data[1];
    if (end &&  _pad_memlen > 0 && postlen > _pad_memlen){
        postlen -= _pad_memlen;
    }
    _post3out.clear();
    _post_idx += postlen;
    _postlen += postlen;
    DBGpdata("post",postlen,postout->dims->data[2],postout->data.f)

    DBGptime()

    auto dnorm_sig_inputs = dnorm_interpreter->signature_inputs("serving_default");
    //dnorm_interpreter->ResizeInputTensorStrict(dnorm_sig_inputs["dnorm_in"],{1,postout->dims->data[1],postout->dims->data[2]});
    //TFLITE_MINIMAL_CHECK(dnorm_interpreter->AllocateTensors() == kTfLiteOk);
    //TfLiteTensor* dnormin = dnorm_interpreter->input_tensor_by_signature("norm_in","serving_default");
    //memcpy(dnormin->data.f,postout->data.f,postout->dims->data[1]*postout->dims->data[2]*sizeof(float));
    dnorm_interpreter->ResizeInputTensorStrict(dnorm_sig_inputs["dnorm_in"],{1,postlen,postout->dims->data[2]});
    TFLITE_MINIMAL_CHECK(dnorm_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* dnormin = dnorm_interpreter->input_tensor_by_signature("norm_in","serving_default");
    TFLITE_MINIMAL_CHECK(dnormin != nullptr);
    //memcpy(dnormin->data.f,_postout.data(),_postout.size()*sizeof(float));
    memcpy(dnormin->data.f,postout->data.f,postlen*postout->dims->data[2]*sizeof(float));
    dnorm_interpreter->Invoke();
    const TfLiteTensor* dnormout = dnorm_interpreter->output_tensor_by_signature("dnorm", "serving_default");
    TFLITE_MINIMAL_CHECK(dnormout != nullptr);

    _dnormout.insert(_dnormout.end(),dnormout->data.f,dnormout->data.f+(dnormout->dims->data[1]*dnormout->dims->data[2]));

    DBGpdata("dnorm", dnormout->dims->data[1],dnormout->dims->data[2],dnormout->data.f)
    DBGptime()

    //vocoder(dnormout->data.f,dnormout->dims->data[1]);
    //if (end)
    //vocoder(_dnormout.data(),_dnormout.size()/82);
    st_vocoder1(end);
    return end;

}
void stTTS::worker_vocoder(stTTS *obj){
    while(true){
        bool end = obj->am_post();
        if (end) break;
    }
}
void stTTS::st_vocoder1(bool endflag){
    int dnorm_len;

    /* mutex */
    dnorm_len = _dnormout.size()/_meldim;
    if (dnorm_len < _hifi0win && !endflag){
    //if (!endflag){
        return;
    }

    auto hifigan0_sig_inputs = hifigan0_interpreter->signature_inputs("serving_default");
    hifigan0_interpreter->ResizeInputTensorStrict(hifigan0_sig_inputs["hifi0_in"],{1,dnorm_len,_meldim});
    TFLITE_MINIMAL_CHECK(hifigan0_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* hifigan0in = hifigan0_interpreter->input_tensor_by_signature("hifi0_in","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan0in != nullptr);
    memcpy(hifigan0in->data.f,_dnormout.data(),dnorm_len*_meldim*sizeof(float));


    hifigan0_interpreter->Invoke();
    const TfLiteTensor* hifigan0out = hifigan0_interpreter->output_tensor_by_signature("hifigan0", "serving_default");
    TFLITE_MINIMAL_CHECK(hifigan0out != nullptr);
    const TfLiteTensor* hifigan0out_exci = hifigan0_interpreter->output_tensor_by_signature("hifigan0_1", "serving_default");
    TFLITE_MINIMAL_CHECK(hifigan0out_exci != nullptr);
    int h0start,h0len;
    if (_hifi0out.size() == 0){
        h0start = 0;
    }else{
        h0start = _hifi0olp;
    }
    if (!endflag){
        h0len = hifigan0out->dims->data[1] - _hifi0olp - h0start;
    }else{
        h0len = hifigan0out->dims->data[1] - h0start;
    }
    _hifi0len += h0len;
    _hifi0out.insert(_hifi0out.end(),hifigan0out->data.f + h0start*hifigan0out->dims->data[2], hifigan0out->data.f + (h0start + h0len)*hifigan0out->dims->data[2]);
    _exciout.insert(_exciout.end(),hifigan0out_exci->data.f + h0start*200*hifigan0out_exci->dims->data[2], hifigan0out_exci->data.f + (h0start+ h0len)*200*hifigan0out_exci->dims->data[2]);
    if (!endflag){
        _dnormout.erase(_dnormout.begin(),_dnormout.begin() + (dnorm_len - 2*_hifi0olp)*_meldim);
    }else{
        _dnormout.clear();
    }

    DBGptime()

    int hifi0out_len = _hifi0out.size()/_hifi1dim;
    if (hifi0out_len < _hifi1win && !endflag) return;

    TfLiteTensor* hifigan1in = hifigan1_interpreter->input_tensor_by_signature("hifi1_in","serving_default");
    TfLiteTensor* hifigan1in_exci = hifigan1_interpreter->input_tensor_by_signature("hifi1_exci","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan1in != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan1in_exci != nullptr);

    bool last = false;
    int h1idx = _hifi1olp;
    int h1step = _hifi1win - 2*_hifi1olp;
    for(; h1idx<hifi0out_len; h1idx+=h1step){
        int padlen = 0;
        if (h1idx + _hifi1win - _hifi1olp > hifi0out_len){
            if (!endflag){
                break;
            }else{
                last = true;
                padlen = _hifi1win - (hifi0out_len - h1idx + _hifi1olp);
                memset(hifigan1in->data.f, 0, _hifi1win*_hifi1dim*sizeof(float));
                memset(hifigan1in_exci->data.f, 0 ,_hifi1win*200*_excidim*sizeof(float));
            }
        }
        memcpy(hifigan1in->data.f,_hifi0out.data() + (h1idx -_hifi1olp)*_hifi1dim, (_hifi1win-padlen)*_hifi1dim*sizeof(float));
        memcpy(hifigan1in_exci->data.f,_exciout.data() + (_hifi1idx - _hifi1olp)*200*_excidim ,(_hifi1win-padlen)*200*_excidim*sizeof(float));
        hifigan1_interpreter->Invoke();
        const TfLiteTensor* hifigan1out = hifigan1_interpreter->output_tensor_by_signature("hifigan1", "serving_default");
        TFLITE_MINIMAL_CHECK(hifigan1out != nullptr);
        int h1start;
        if (_hifi1out.size() == 0){
            h1start = 0;
        }else{
            h1start = _hifi1olp;
        }
        if (!last){
            _hifi1out.insert(_hifi1out.end(),hifigan1out->data.f + h1start*_hifi1up*hifigan1out->dims->data[2], hifigan1out->data.f + (_hifi1win - _hifi1olp)*_hifi1up*hifigan1out->dims->data[2]);
            _hifi1len += (_hifi1win - _hifi1olp - h1start);
        }else{
            _hifi1out.insert(_hifi1out.end(),hifigan1out->data.f + h1start*_hifi1up*hifigan1out->dims->data[2], hifigan1out->data.f + (_hifi1win - padlen)*_hifi1up*hifigan1out->dims->data[2]);
            _hifi1len += (_hifi1win - padlen - h1start);
        }
        _hifi1idx += h1step;
        if (last) break;
    }
    if (!endflag){
        _hifi0out.erase(_hifi0out.begin(),_hifi0out.begin()+ (h1idx-_hifi1olp)*_hifi1dim);
    }else{
        _hifi0out.clear();
    }
    DBGptime()

    hifi0out_len = _hifi0out.size()/_hifi1dim;
    DBGprint("hifi0out",hifi0out_len)
    st_vocoder2(endflag);
    return ;
}
void stTTS::st_vocoder2(bool end){
    int hifi1out_len = _hifi1out.size()/_hifi2dim;
    if (hifi1out_len < _hifi2win && !end) return;

    TfLiteTensor* hifigan2in = hifigan2_interpreter->input_tensor_by_signature("hifi2_in","serving_default");
    TfLiteTensor* hifigan2in_exci = hifigan2_interpreter->input_tensor_by_signature("hifi2_exci","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan2in != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan2in_exci != nullptr);

    bool last = false;
    int h2idx = _hifi2olp;
    int h2step = _hifi2win - 2*_hifi2olp;
    for(; h2idx<hifi1out_len; h2idx+=h2step){
        int padlen = 0;
        if (h2idx + _hifi2win - _hifi2olp > hifi1out_len){
            if (!end){
                break;
            }else{
                last = true;
                padlen = _hifi2win - (hifi1out_len - h2idx + _hifi2olp);
                memset(hifigan2in->data.f, 0, _hifi2win*_hifi2dim*sizeof(float));
                memset(hifigan2in_exci->data.f, 0 ,_hifi2win*20*_excidim*sizeof(float));
            }
        }
        memcpy(hifigan2in->data.f,_hifi1out.data() + (h2idx -_hifi2olp)*_hifi2dim, (_hifi2win-padlen)*_hifi2dim*sizeof(float));
        memcpy(hifigan2in_exci->data.f,_exciout.data() + (_hifi2idx - _hifi2olp)*20*_excidim ,(_hifi2win-padlen)*20*_excidim*sizeof(float));
        hifigan2_interpreter->Invoke();
        const TfLiteTensor* hifigan2out = hifigan2_interpreter->output_tensor_by_signature("hifigan2", "serving_default");
        TFLITE_MINIMAL_CHECK(hifigan2out != nullptr);
        int h2start;
        if (_hifi2out.size() == 0){
            h2start = 0;
        }else{
            h2start = _hifi2olp;
        }
        if (!last){
            _hifi2out.insert(_hifi2out.end(),hifigan2out->data.f + h2start*_hifi2up*hifigan2out->dims->data[2], hifigan2out->data.f + (_hifi2win - _hifi2olp)*_hifi2up*hifigan2out->dims->data[2]);
        }else{
            _hifi2out.insert(_hifi2out.end(),hifigan2out->data.f + h2start*_hifi2up*hifigan2out->dims->data[2], hifigan2out->data.f + (_hifi2win - padlen)*_hifi2up*hifigan2out->dims->data[2]);
        }
        _hifi2idx += h2step;
        if (last) break;
    }
    if (!end){
        _hifi1out.erase(_hifi1out.begin(),_hifi1out.begin()+ (h2idx-_hifi2olp)*_hifi2dim);
    }else{
        _hifi1out.clear();
    }

    hifi1out_len = _hifi1out.size()/_hifi2dim;

    int hifi2out_len = _hifi2out.size()/_hifi3dim;
    st_vocoder3(end);
}
void stTTS::st_vocoder3(bool end){
    int hifi2out_len = _hifi2out.size()/_hifi3dim;
    if (hifi2out_len < _hifi3win && !end) return;

    TfLiteTensor* hifigan3in = hifigan3_interpreter->input_tensor_by_signature("hifi3_in","serving_default");
    TfLiteTensor* hifigan3in_exci = hifigan3_interpreter->input_tensor_by_signature("hifi3_exci","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan3in != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan3in_exci != nullptr);


    bool last = false;
    int h3idx = _hifi3olp;
    int h3step = _hifi3win - 2*_hifi3olp;
    for(; h3idx<hifi2out_len; h3idx+=h3step){
        int padlen = 0;
        if (h3idx + _hifi3win - _hifi3olp > hifi2out_len){
            if (!end){
                break;
            }else{
                last = true;
                padlen = _hifi3win - (hifi2out_len - h3idx + _hifi3olp);
                memset(hifigan3in->data.f, 0, _hifi3win*_hifi3dim*sizeof(float));
                memset(hifigan3in_exci->data.f, 0 ,_hifi3win*4*_excidim*sizeof(float));
            }
        }
        memcpy(hifigan3in->data.f,_hifi2out.data() + (h3idx -_hifi3olp)*_hifi3dim, (_hifi3win-padlen)*_hifi3dim*sizeof(float));
        memcpy(hifigan3in_exci->data.f,_exciout.data() + (_hifi3idx - _hifi3olp)*4*_excidim ,(_hifi3win-padlen)*4*_excidim*sizeof(float));
        hifigan3_interpreter->Invoke();
        const TfLiteTensor* hifigan3out = hifigan3_interpreter->output_tensor_by_signature("hifigan3", "serving_default");
        TFLITE_MINIMAL_CHECK(hifigan3out != nullptr);
        int h3start;
        if (_hifi3out.size() == 0){
            h3start = 0;
        }else{
            h3start = _hifi3olp;
        }
        if (!last){
            _hifi3out.insert(_hifi3out.end(),hifigan3out->data.f + h3start*_hifi3up*hifigan3out->dims->data[2], hifigan3out->data.f + (_hifi3win - _hifi3olp)*_hifi3up*hifigan3out->dims->data[2]);
            _hifi3len += (_hifi3win - _hifi3olp - h3start);
        }else{
            _hifi3out.insert(_hifi3out.end(),hifigan3out->data.f + h3start*_hifi3up*hifigan3out->dims->data[2], hifigan3out->data.f + (_hifi3win - padlen)*_hifi3up*hifigan3out->dims->data[2]);
            _hifi3len += (_hifi3win - padlen - h3start);
        }
        _hifi3idx += h3step;
        if (last) break;
    }
    if (!end){
        _hifi2out.erase(_hifi2out.begin(),_hifi2out.begin()+ (h3idx-_hifi3olp)*_hifi3dim);
    }else{
        _hifi2out.clear();
    }

    hifi2out_len = _hifi2out.size()/_hifi3dim;

    int hifi3out_len = _hifi3out.size()/_hifi4dim;
    st_vocoder4(end);
}
void stTTS::st_vocoder4(bool end){
    int hifi3out_len = _hifi3out.size()/_hifi4dim;
    if (hifi3out_len < _hifi4win && !end) return;

    TfLiteTensor* hifigan4in = hifigan4_interpreter->input_tensor_by_signature("hifi4_in","serving_default");
    TfLiteTensor* hifigan4in_exci = hifigan4_interpreter->input_tensor_by_signature("hifi4_exci","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan4in != nullptr);
    TFLITE_MINIMAL_CHECK(hifigan4in_exci != nullptr);

    bool last = false;
    int h4idx = _hifi4olp;
    int h4step = _hifi4win -2*_hifi4olp;
    for(; h4idx<hifi3out_len; h4idx+=h4step){
        int padlen = 0;
        if (h4idx + _hifi4win - _hifi4olp > hifi3out_len){
            if (!end){
                break;
            }else{
                last = true;
                padlen = _hifi4win - (hifi3out_len - h4idx + _hifi4olp);
                memset(hifigan4in->data.f, 0, _hifi4win*_hifi4dim*sizeof(float));
                memset(hifigan4in_exci->data.f, 0 ,_hifi4win*2*_excidim*sizeof(float));
            }
        }
        memcpy(hifigan4in->data.f,_hifi3out.data() + (h4idx -_hifi4olp)*_hifi4dim, (_hifi4win-padlen)*_hifi4dim*sizeof(float));
        memcpy(hifigan4in_exci->data.f,_exciout.data() + (_hifi4idx - _hifi4olp)*2*_excidim ,(_hifi4win-padlen)*2*_excidim*sizeof(float));
        hifigan4_interpreter->Invoke();
        const TfLiteTensor* hifigan4out = hifigan4_interpreter->output_tensor_by_signature("hifigan4", "serving_default");
        TFLITE_MINIMAL_CHECK(hifigan4out != nullptr);
        int h4start;
        if (_hifi4out.size() == 0){
            h4start = 0;
        }else{
            h4start = _hifi4olp;
        }
        if (!last){
            _hifi4out.insert(_hifi4out.end(),hifigan4out->data.f + h4start*_hifi4up*hifigan4out->dims->data[2], hifigan4out->data.f + (_hifi4win - _hifi4olp)*_hifi4up*hifigan4out->dims->data[2]);
            _hifi4len += (_hifi4win - _hifi4olp - h4start);
        }else{
            _hifi4out.insert(_hifi4out.end(),hifigan4out->data.f + h4start*_hifi4up*hifigan4out->dims->data[2], hifigan4out->data.f + (_hifi4win - padlen)*_hifi4up*hifigan4out->dims->data[2]);
            _hifi4len +=( _hifi4win - padlen - h4start);
        }
        _hifi4idx += h4step;
        if (last) break;
    }
    if (!end){
        _hifi3out.erase(_hifi3out.begin(),_hifi3out.begin()+ (h4idx-_hifi4olp)*_hifi4dim);
    }else{
        _hifi3out.clear();
    }

    hifi3out_len = _hifi3out.size()/_hifi4dim;

    int hifi4out_len = _hifi4out.size()/_hifi5dim;
    st_vocoder5(end);
}
void stTTS::st_vocoder5(bool end){
    int hifi4out_len = _hifi4out.size()/_hifi5dim;

    auto hifigan5_sig_inputs = hifigan5_interpreter->signature_inputs("serving_default");
    hifigan5_interpreter->ResizeInputTensorStrict(hifigan5_sig_inputs["hifi5_in"],{1,hifi4out_len,_hifi5dim});
    TFLITE_MINIMAL_CHECK(hifigan5_interpreter->AllocateTensors() == kTfLiteOk);
    TfLiteTensor* hifigan5in = hifigan5_interpreter->input_tensor_by_signature("hifi5_in","serving_default");
    TFLITE_MINIMAL_CHECK(hifigan5in != nullptr);
    memcpy(hifigan5in->data.f,_hifi4out.data(),hifi4out_len*_hifi5dim*sizeof(float));
    hifigan5_interpreter->Invoke();
    const TfLiteTensor* hifigan5out = hifigan5_interpreter->output_tensor_by_signature("hifigan5", "serving_default");
    TFLITE_MINIMAL_CHECK(hifigan5out != nullptr);
    if (!end){
        _hifi4out.erase(_hifi4out.begin(),_hifi4out.end()-2*_hifi5olp*_hifi5dim);
    }else{
        _hifi4out.clear();
    }

    hifi4out_len = _hifi4out.size()/_hifi5dim;
    int len = hifigan5out->dims->data[1];
    int dim = hifigan5out->dims->data[2];
    int h5start,h5end;
    if (_pcmlen == 0){
        h5start = 0;
    }else{
        h5start = _hifi5olp;
    }
    if (!end){
        h5end = len - _hifi5olp;
    }else{
        h5end = len;
    }
    for(int i=h5start;i<h5end;i++){
        for(int j=0;j<dim;j++){
            _pcm.push_back(short(*(hifigan5out->data.f+i*dim+j)*32768.0));
        }
    }
    DBGptime()
    int pcm_len = _pcm.size();
    _pcmlen += pcm_len;
    _pcm_callback(_pcm,_args,false);
    _pcm.clear();
    //if (end){
    //    std::string out_name(std::to_string(_pcmid)+"debugcpp.pcm");
    //    ofstream wav_ofs(out_name, std::ios::binary|std::ios::out);
    //    wav_ofs.write((char*)_pcm.data(),_pcm.size()*2);
    //}
}
stTTSInst::stTTSInst(std::string &model_path,std::string &model_fix, void (*pcm_callback)(std::vector<short> &pcm,void *args,bool endf),void* args){
    _TTSInst = std::make_shared<stTTS>(model_path,model_fix,pcm_callback,args);
}
void stTTSInst::input(const std::vector<std::vector<std::vector<std::string>>> &sentences){
    _TTSInst->input_txt(sentences);
}
